package com.codedancer.campus.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codedancer.campus.client.service.IDynamicService;
import com.codedancer.campus.client.service.bo.dynamic.DynamicPageSearchBo;
import com.codedancer.campus.client.service.bo.dynamic.WhisperPublishBo;
import com.codedancer.campus.client.service.vo.dynamic.DynamicPageVo;
import com.codedancer.campus.client.service.vo.dynamic.DynamicVo;
import com.codedancer.campus.common.dataresource.ExternalApiData;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.UUIDGenerator;
import com.codedancer.campus.enums.DynamicStatus;
import com.codedancer.campus.enums.DynamicType;
import com.codedancer.campus.mapper.CircleLabelMapper;
import com.codedancer.campus.mapper.CircleMapper;
import com.codedancer.campus.mapper.DynamicCircleLabelMapper;
import com.codedancer.campus.mapper.DynamicImageMapper;
import com.codedancer.campus.mapper.DynamicKudosMapper;
import com.codedancer.campus.mapper.DynamicMapper;
import com.codedancer.campus.mapper.PlateMapper;
import com.codedancer.campus.mapper.UserSchoolMapper;
import com.codedancer.campus.po.Circle;
import com.codedancer.campus.po.CircleLabel;
import com.codedancer.campus.po.Dynamic;
import com.codedancer.campus.po.DynamicCircleLabel;
import com.codedancer.campus.po.DynamicImage;
import com.codedancer.campus.po.DynamicKudos;
import com.codedancer.campus.po.Plate;
import com.codedancer.campus.po.UserSchool;
import com.codedancer.campus.qo.dynamic.DynamicSearchQo;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class DynamicServiceImpl implements IDynamicService {

    @Autowired
    private DynamicMapper dynamicMapper;
    @Autowired
    private CircleMapper circleMapper;
    @Autowired
    private PlateMapper plateMapper;
    @Autowired
    private UserSchoolMapper userSchoolMapper;
    @Autowired
    private DynamicImageMapper dynamicImageMapper;
    @Autowired
    private CircleLabelMapper circleLabelMapper;
    @Autowired
    private DynamicCircleLabelMapper dynamicCircleLabelMapper;

    @Autowired
    private DynamicKudosMapper dynamicKudosMapper;
    @Autowired
    private ExternalApiData externalApiData;

    /**
     * 发布悄悄话
     *
     * @param whisperPublishBo
     */
    @Override
    public void publishWhisper(WhisperPublishBo whisperPublishBo) {
        // 先校验数据合格性
        checkWhisperData(whisperPublishBo);
        Dynamic dynamic = BeanUtil.copyProperties(whisperPublishBo, Dynamic.class);
        dynamic.setPublishUserUuid(whisperPublishBo.getCurrentUuid());
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", whisperPublishBo.getCurrentUuid());
        if (ObjectUtil.isEmpty(userSchool)) {
            throw new BusinessException("你绑定的学校已不存在，请联系管理员");
        }
        dynamic.setUuid(UUIDGenerator.getUUID());
        dynamic.setPublishSchoolUuid(userSchool.getSchoolUuid());
        dynamic.setStatus(DynamicStatus.PENDING_REVIEW);
        dynamic.setType(DynamicType.WHISPER);
        dynamicMapper.insert(dynamic);
        // 保存图片信息
        if (CollectionUtil.isNotEmpty(whisperPublishBo.getImageUrls())) {
            for (String imageUrl : whisperPublishBo.getImageUrls()) {
                DynamicImage dynamicImage = DynamicImage.builder()
                    .uuid(UUIDGenerator.getUUID())
                    .dynamicUuid(dynamic.getUuid())
                    .imageUrl(imageUrl).build();
                dynamicImageMapper.insert(dynamicImage);
            }
        }
        // 保存动态标签
        for (String labelUuid : whisperPublishBo.getLabels()) {
            DynamicCircleLabel dynamicCircleLabel = DynamicCircleLabel.builder()
                .uuid(UUIDGenerator.getUUID())
                .dynamicUuid(dynamic.getUuid())
                .circleLabelUuid(labelUuid).build();
            dynamicCircleLabelMapper.insert(dynamicCircleLabel);
        }
    }

    /**
     * 分页查询动态
     *
     * @param dynamicPageSearchBo
     * @return
     */
    @Override
    public IPage<DynamicPageVo> page(DynamicPageSearchBo dynamicPageSearchBo) {
        DynamicSearchQo dynamicSearchQo = BeanUtil
            .copyProperties(dynamicPageSearchBo, DynamicSearchQo.class);
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", dynamicPageSearchBo.getCurrentUserUuid());
        dynamicSearchQo.setPublishSchoolUuid(userSchool.getSchoolUuid());
        IPage<Dynamic> dynamicIPage = dynamicMapper.page2Client(
            new Page<Dynamic>(dynamicPageSearchBo.getPage(), dynamicPageSearchBo.getSize()),
            dynamicSearchQo);
        List<DynamicPageVo> dynamicPageVos;
        IPage<DynamicPageVo> dynamicPageVoIPage = new Page<>();
        dynamicPageVos = dynamicIPage.getRecords().stream().map(dynamic -> {
            DynamicPageVo dynamicPageVo = BeanUtil.copyProperties(dynamic, DynamicPageVo.class);
            dynamicPageVo.setPublishUserNickName(dynamic.getPublishUser().getNickName());
            dynamicPageVo.setPublishUserAvatar(dynamic.getPublishUser().getAvatar());
            dynamicPageVo.setPublishCircleTitle(dynamic.getPublishCircle().getTitle());
            // 获取动态图片
            List<DynamicImage> dynamicImages = dynamicImageMapper.selectListByColumn("dynamic_uuid",
                dynamic.getUuid());
            dynamicPageVo.setImages(
                dynamicImages.stream().map(DynamicImage::getImageUrl).collect(
                    Collectors.toList()));
            // 获取动态绑定的标签
            List<DynamicCircleLabel> dynamicCircleLabels = dynamicCircleLabelMapper.selectListByColumn(
                "dynamic_uuid", dynamic.getUuid());
            // 获取标签
            List<CircleLabel> circleLabels = circleLabelMapper.selectListByUuids(
                dynamicCircleLabels.stream().map(DynamicCircleLabel::getCircleLabelUuid).collect(
                    Collectors.toList()));
            dynamicPageVo
                .setLabels(circleLabels.stream().map(CircleLabel::getName).collect(
                    Collectors.toList()));
            return dynamicPageVo;
        }).collect(Collectors.toList());
        dynamicPageVoIPage.setRecords(dynamicPageVos);
        return dynamicPageVoIPage;
    }

    /**
     * 动态详情
     *
     * @param uuid
     * @return
     */
    @Override
    public DynamicVo detail(String uuid) {
        Dynamic dynamic = dynamicMapper.detail(uuid);
        if (ObjectUtil.isEmpty(dynamic)) {
            throw new BusinessException("动态不存在");
        }
        DynamicVo dynamicVo = BeanUtil.copyProperties(dynamic, DynamicVo.class);
        dynamicVo.setPublishUserNickName(dynamic.getPublishUser().getNickName());
        dynamicVo.setPublishUserAvatar(dynamic.getPublishUser().getAvatar());
        dynamicVo.setPublishUserUuid(dynamic.getPublishUser().getUuid());
        dynamicVo.setPublishCircleTitle(dynamic.getPublishCircle().getTitle());
        dynamicVo.setCircleUuid(dynamic.getPublishCircle().getUuid());
        dynamicVo.setImages(
            dynamic.getDynamicImages().stream().map(DynamicImage::getImageUrl).collect(
                Collectors.toList()));
        dynamicVo
            .setLabels(dynamic.getCircleLabels().stream().map(CircleLabel::getName).collect(
                Collectors.toList()));
        return dynamicVo;
    }

    /**
     * 查询用户发布的动态
     *
     * @param dynamicPageSearchBo
     * @return
     */
    @Override
    public IPage<DynamicPageVo> page2User(DynamicPageSearchBo dynamicPageSearchBo) {
        DynamicSearchQo dynamicSearchQo = BeanUtil
            .copyProperties(dynamicPageSearchBo, DynamicSearchQo.class);
        IPage<Dynamic> dynamicIPage = dynamicMapper.page2User(
            new Page<Dynamic>(dynamicPageSearchBo.getPage(), dynamicPageSearchBo.getSize()),
            dynamicSearchQo);
        List<DynamicPageVo> dynamicPageVos;
        IPage<DynamicPageVo> dynamicPageVoIPage = new Page<>();
        dynamicPageVos = dynamicIPage.getRecords().stream().map(dynamic -> {
            DynamicPageVo dynamicPageVo = BeanUtil.copyProperties(dynamic, DynamicPageVo.class);
            dynamicPageVo.setPublishUserNickName(dynamic.getPublishUser().getNickName());
            dynamicPageVo.setPublishUserAvatar(dynamic.getPublishUser().getAvatar());
            dynamicPageVo.setPublishCircleTitle(dynamic.getPublishCircle().getTitle());
            // 获取动态图片
            List<DynamicImage> dynamicImages = dynamicImageMapper.selectListByColumn("dynamic_uuid",
                dynamic.getUuid());
            dynamicPageVo.setImages(
                dynamicImages.stream().map(DynamicImage::getImageUrl).collect(
                    Collectors.toList()));
            // 获取动态绑定的标签
            List<DynamicCircleLabel> dynamicCircleLabels = dynamicCircleLabelMapper.selectListByColumn(
                "dynamic_uuid", dynamic.getUuid());
            // 获取标签
            List<CircleLabel> circleLabels = circleLabelMapper.selectListByUuids(
                dynamicCircleLabels.stream().map(DynamicCircleLabel::getCircleLabelUuid).collect(
                    Collectors.toList()));
            dynamicPageVo
                .setLabels(circleLabels.stream().map(CircleLabel::getName).collect(
                    Collectors.toList()));
            return dynamicPageVo;
        }).collect(Collectors.toList());
        dynamicPageVoIPage.setRecords(dynamicPageVos);
        return dynamicPageVoIPage;
    }

    /**
     * 删除动态
     *
     * @param uuid
     */
    @Override
    public void delete(String uuid) {
        if (!dynamicMapper.existsByUuId(uuid)) {
            throw new BusinessException("动态不存在");
        }
        dynamicMapper.deleteById(uuid);
    }

    /**
     * 分页查询某个圈子下的动态
     *
     * @param dynamicPageSearchBo
     * @return
     */
    @Override
    public IPage<DynamicPageVo> pageByCircleUuid(DynamicPageSearchBo dynamicPageSearchBo) {
        if (!circleMapper.existsByUuId(dynamicPageSearchBo.getCircleUuid())) {
            throw new BusinessException("圈子不存在");
        }
        DynamicSearchQo dynamicSearchQo = BeanUtil
            .copyProperties(dynamicPageSearchBo, DynamicSearchQo.class);
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", dynamicPageSearchBo.getCurrentUserUuid());
        dynamicSearchQo.setPublishSchoolUuid(userSchool.getSchoolUuid());
        IPage<Dynamic> dynamicIPage = dynamicMapper.pageByCircleUuid(
            new Page<Dynamic>(dynamicPageSearchBo.getPage(), dynamicPageSearchBo.getSize()),
            dynamicSearchQo);
        List<DynamicPageVo> dynamicPageVos;
        IPage<DynamicPageVo> dynamicPageVoIPage = new Page<>();
        dynamicPageVos = dynamicIPage.getRecords().stream().map(dynamic -> {
            DynamicPageVo dynamicPageVo = BeanUtil.copyProperties(dynamic, DynamicPageVo.class);
            dynamicPageVo.setPublishUserNickName(dynamic.getPublishUser().getNickName());
            dynamicPageVo.setPublishUserAvatar(dynamic.getPublishUser().getAvatar());
            dynamicPageVo.setPublishCircleTitle(dynamic.getPublishCircle().getTitle());
            // 获取动态图片
            List<DynamicImage> dynamicImages = dynamicImageMapper.selectListByColumn("dynamic_uuid",
                dynamic.getUuid());
            dynamicPageVo.setImages(
                dynamicImages.stream().map(DynamicImage::getImageUrl).collect(
                    Collectors.toList()));
            // 获取动态绑定的标签
            List<DynamicCircleLabel> dynamicCircleLabels = dynamicCircleLabelMapper.selectListByColumn(
                "dynamic_uuid", dynamic.getUuid());
            // 获取标签
            List<CircleLabel> circleLabels = circleLabelMapper.selectListByUuids(
                dynamicCircleLabels.stream().map(DynamicCircleLabel::getCircleLabelUuid).collect(
                    Collectors.toList()));
            dynamicPageVo
                .setLabels(circleLabels.stream().map(CircleLabel::getName).collect(
                    Collectors.toList()));
            return dynamicPageVo;
        }).collect(Collectors.toList());
        dynamicPageVoIPage.setRecords(dynamicPageVos);
        return dynamicPageVoIPage;
    }

    /**
     * 开启评论
     *
     * @param uuid
     */
    @Override
    public void openComment(String uuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        if (!dynamic.getStatus().equals(DynamicStatus.PASSED)) {
            throw new BusinessException("动态未审核或未通过");
        }
        dynamic.setIsOpenComment(true);
        dynamicMapper.updateById(dynamic);
    }

    /**
     * 关闭评论
     *
     * @param uuid
     */
    @Override
    public void closeComment(String uuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        if (!dynamic.getStatus().equals(DynamicStatus.PASSED)) {
            throw new BusinessException("动态未审核或未通过");
        }
        dynamic.setIsOpenComment(false);
        dynamicMapper.updateById(dynamic);
    }

    /**
     * 修改悄悄话
     *
     * @param whisperPublishBo
     */
    @Override
    public void updateWhisper(WhisperPublishBo whisperPublishBo) {
        Dynamic dynamic = dynamicMapper.findById(whisperPublishBo.getUuid())
            .orElseThrow(() -> new BusinessException("动态不存在"));
        if (dynamic.examineCountIsGtFive()) {
            throw new BusinessException("不通过次数已大于五次，不能提交审核");
        }
        checkWhisperData(whisperPublishBo);
        BeanUtil.copyProperties(whisperPublishBo, dynamic);
        dynamic.setStatus(DynamicStatus.PENDING_REVIEW);
        dynamicMapper.updateById(dynamic);
        // 先删除绑定的标签
        dynamicCircleLabelMapper.deleteByColumn("dynamic_uuid", dynamic.getUuid());
        // 循环添加标签
        for (String labelUuid : whisperPublishBo.getLabels()) {
            DynamicCircleLabel dynamicCircleLabel = DynamicCircleLabel.builder()
                .uuid(UUIDGenerator.getUUID())
                .dynamicUuid(dynamic.getUuid())
                .circleLabelUuid(labelUuid).build();
            dynamicCircleLabelMapper.insert(dynamicCircleLabel);
        }
        // 先删除图片信息
        dynamicImageMapper.deleteByColumn("dynamic_uuid", dynamic.getUuid());
        // 保存图片信息
        if (CollectionUtil.isNotEmpty(whisperPublishBo.getImageUrls())) {
            for (String imageUrl : whisperPublishBo.getImageUrls()) {
                DynamicImage dynamicImage = DynamicImage.builder()
                    .uuid(UUIDGenerator.getUUID())
                    .dynamicUuid(dynamic.getUuid())
                    .imageUrl(imageUrl).build();
                dynamicImageMapper.insert(dynamicImage);
            }
        }
    }

    /**
     * 隐藏
     *
     * @param uuid
     */
    @Override
    public void hide(String uuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        if (!dynamic.isPassExamine()) {
            throw new BusinessException("该动态处于未审核或者未通过状态");
        }
        dynamic.setIsHide(true);
        dynamicMapper.updateById(dynamic);
    }

    /**
     * 显示
     *
     * @param uuid
     */
    @Override
    public void display(String uuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        if (!dynamic.isPassExamine()) {
            throw new BusinessException("该动态处于未审核或者未通过状态");
        }
        dynamic.setIsHide(false);
        dynamicMapper.updateById(dynamic);
    }

    /**
     * 同步自由广场
     *
     * @param uuid
     */
    @Override
    public void syncLibertySquare(String uuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        if (!dynamic.getStatus().equals(DynamicStatus.PASSED)) {
            throw new BusinessException("动态未审核或未通过，不能同步");
        }
        dynamic.setIsSyncLibertySquare(true);
        dynamicMapper.updateById(dynamic);
    }

    /**
     * 取消同步自由广场
     *
     * @param uuid
     */
    @Override
    public void cancelSyncLibertySquare(String uuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        if (!dynamic.getStatus().equals(DynamicStatus.PASSED)) {
            throw new BusinessException("动态未审核或未通过，不能同步");
        }
        dynamic.setIsSyncLibertySquare(false);
        dynamicMapper.updateById(dynamic);
    }

    /**
     * 动态点赞
     *
     * @param uuid
     * @param currentLoginUuid
     */
    @Override
    public void kudos(String uuid, String currentLoginUuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        // 判断是否可以点赞或者取消点赞
        if (!dynamic.isCanKudosOrCancel()) {
            throw new BusinessException("动态状态错误，不能点赞");
        }
        // 保存点赞记录
        DynamicKudos dynamicKudos = DynamicKudos.builder()
            .uuid(UUIDGenerator.getUUID())
            .dynamicUuid(uuid)
            .kudosUserUuid(currentLoginUuid)
            .build();
        dynamicKudosMapper.insert(dynamicKudos);
    }

    /**
     * 取消点赞
     *
     * @param uuid
     * @param currentLoginUuid
     */
    @Override
    public void cancelKudos(String uuid, String currentLoginUuid) {
        Dynamic dynamic = dynamicMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("动态不存在"));
        // 判断是否可以点赞或者取消点赞
        if (!dynamic.isCanKudosOrCancel()) {
            throw new BusinessException("动态状态错误，不能点赞");
        }
        // 删除点赞记录
        dynamicKudosMapper.deleteByDynamicUuidAndUserUuid(uuid, currentLoginUuid);
    }

    /**
     * 动态是否点赞
     *
     * @param uuid
     * @param currentLoginUuid
     * @return
     */
    @Override
    public Boolean isKudos(String uuid, String currentLoginUuid) {
        return dynamicKudosMapper.isExistsByDynamicUuidAndUserUuid(uuid, currentLoginUuid);
    }

    /**
     * 校验悄悄话数据合格性
     *
     * @param whisperPublishBo
     */
    private void checkWhisperData(WhisperPublishBo whisperPublishBo) {
        if (externalApiData.checkSensitiveWords(whisperPublishBo.getContent())) {
            throw new BusinessException("动态内容存在敏感词，请检查");
        }
        // 校验圈子
        Circle circle = circleMapper.findById(whisperPublishBo.getCircleUuid())
            .orElseThrow(() -> new BusinessException("圈子不存在"));
        if (circle.getDisabled()) {
            throw new BusinessException("圈子已被禁用，请重新选择");
        }
        // 校验板块
        Plate plate = plateMapper.findById(whisperPublishBo.getPlateUuid())
            .orElseThrow(() -> new BusinessException("板块不存在"));
        if (!plate.getCode().equals("treeHole")) {
            throw new BusinessException("板块错误，请重新选择");
        }
        // 判断圈子标签是否存在
        if (CollectionUtil.isEmpty(whisperPublishBo.getLabels())) {
            throw new BusinessException("请选择圈子标签");
        }
        for (String labelUuid : whisperPublishBo.getLabels()) {
            if (!circleLabelMapper.existsByUuId(labelUuid)) {
                throw new BusinessException("标签不存在，请选择正确的圈子标签");
            }
        }
    }
}
